# -*- coding: utf-8 -*-

from dataclasses import dataclass
import os, sys, re, codecs, binascii, cgi, cgitb, datetime, pickle, sqlite3

from flask import render_template
from flask import request
from flask import jsonify


selfpath = 'data/lodger1/'

class Lodger:
	def __init__(self):
		self.storage = DBStorage(self)
		self.io = FlaskInputOutput(request)
		self.restio = RESTInputOutput(request)
		
	def ShowForm(self, id):
		return self.storage.GetItem(id).Output(self.io)
		
	def ShowLodger(self):
		return render_template('lodger1/lodger.tpl', items=self.storage.GetItems(), selfurl='/'+request.url_rule.rule.split('/')[1])
		
	def Add(self):
		item = self.storage.GetItem(int(self.io.Input('id')))
		item.Input(self.io)
		self.storage.Add(item);
		return self.ShowLodger()
			
	def Delete(self, id):
		self.storage.Delete(id)
		return self.ShowLodger()

	def APILodger(self):
		ids = []
		for item in self.storage.GetItems():
			ids.append([item.id, item.title])
		return jsonify({'ids': ids})
		
	def APIAdd(self):
		print('**********************')
		print(request.json)
		item = self.storage.GetItem(0)
		item.Input(self.restio)
		self.storage.Add(item);
		return ''
		
	def APIGet(self, id):
		item = self.storage.GetItem(id)
		print(item.__dict__)
		return jsonify(item.__dict__)
		
	def APISet(self, id):
		item = self.storage.GetItem(id)
		item.Input(self.restio)
		self.storage.Add(item);
		return ''
		
	def APIDelete(self, id):
		self.storage.Delete(id)
		return ''

class PickleStorage:
	def __init__ (self, lodger):
		self.lodger = lodger
		try:
			self.Load()
		except:
			self.items = {}
			self.maxid = 0

	def Load(self):
		if not os.path.exists(selfpath):
		    os.mkdir(selfpath)
		with open(selfpath+'lodger.db', 'rb') as f:
			(self.maxid, self.items) = pickle.load(f)
		
	def Store(self):
		with open(selfpath+'lodger.db', 'wb') as f:
			pickle.dump((self.maxid, self.items), f)

	def GetItem(self, id):
		if id <= 0:
			return LodgerItem()
		else:
			return self.items[id]

	def Add(self, item):
		if item.id <= 0:
			self.maxid += 1;
			item.id = self.maxid
			self.items[item.id] = item
			
	def Delete(self, id):
		del self.items[id]
		
	def GetItems(self):
		for(id, item) in self.items.items():
			yield(item)

class DBStorage:
	def __init__ (self, lodger):
		self.Load()
		
	def Load(self):
		if not os.path.exists(selfpath):
		    os.mkdir(selfpath)
		self.db = sqlite3.connect(selfpath+'lodger.sqlite', detect_types=sqlite3.PARSE_DECLTYPES)
		self.db.execute("""
				   create table if not exists lodger(
					   id integer primary key autoincrement,
					   fio text,
					   room text,
					   count text,
                       child text,
					   time timestamp
					   )""")
		self.db.row_factory = sqlite3.Row
		self.dbc = self.db.cursor()

		
	def Store(self):
		self.db.commit()
		self.db.close()

	def GetItem(self, id):
		item = LodgerItem()
		if id > 0:
			self.dbc.execute("select * from lodger where id=?", (id,))
			item.DBLoad(self.dbc.fetchone())
		return item

	def Add(self, item):
		item.DBStore(self.db)
			
	def Delete(self, id):
		self.db.execute("delete from lodger where id=?", (id,))
		
	def GetItems(self):
		self.dbc.execute("select * from lodger order by id desc")
		for r in self.dbc:
			item = LodgerItem()
			item.DBLoad(r)
			yield(item)

class RESTInputOutput:
	def __init__(self, io):
		self.io = io

	def Input(self, field, defval=None):
		return self.io.json.get(field, defval)
	
	def Output(self, item):
		print(item) 

class ConsoleInputOutput:
	def Input(self, field, defval=None):
		return input(field)
	
	def Output(self, item):
		print(item) 

	def __str__(self):
		return ''

class FlaskInputOutput:
	def __init__(self, io):
		self.io = io
	
	def Input(self, field, defval=None):
		return self.io.form.get(field, defval)
	
	def Output(self, item):
		return render_template('lodger1/form.tpl', it=item, selfurl='/'+request.url_rule.rule.split('/')[1])

@dataclass
class LodgerItem:
	id: int = 0
	fio: str = ''
	room: str = ''
	count: str = ''
	child: str = ''
	time = 0
   
	def __post_init__(self):
		self.time = datetime.datetime.now()
#		self.io = ConsoleInputOutput()

	def Show(self):
		return "BootItem Edit"
	
	def DBLoad(self, r):
		self.id = r['id']
		self.fio = r['fio']
		self.room = r['room']
		self.count = r['count']
		self.child = r['child']
		self.time = r['time']
		
	def DBStore(self, db):
		if not self.id or int(self.id) == 0:
			db.execute("insert into lodger values(NULL, ?, ?, ?, ?, ?)", (self.fio, self.room, self.count, self.child, self.time))
		else:
			db.execute("update lodger set fio=?, room=?, count=?, child=?, time=? where id=?", (self.fio, self.room, self.count, self.child, self.time, self.id));
			
	
	def Input(self, io):
		self.id = int(io.Input('id', self.id))
		self.fio = io.Input('fio')
		self.room = io.Input('room')
		self.count = io.Input('count')
		self.child = io.Input('child')
	
	def Output(self, io):
		return io.Output(self)


